<template>
  <a-drawer
      :closable="true"
      :title="title"
      :visible="visible"
      :width="width"
      @close="close"
      destroyOnClose
  >
    <a-spin :spinning="confirmLoading">
      <a-form-model
          ref="instanceForm"
          :label-col="labelCol"
          :model="model"
          :wrapper-col="wrapperCol"
      >
        <a-form-model-item ref="code" :rules="rules.code" label="实例标识" prop="code">
          <a-input v-model="model.code" placeholder="请输入实例标识"/>
        </a-form-model-item>
        <a-form-model-item ref="name" :rules="rules.name" label="实例名称" prop="name">
          <a-input v-model="model.name" placeholder="请输入实例名称" />
        </a-form-model-item>
        <a-form-model-item ref="modelBy" :rules="rules.modelBy" label="设备模型" prop="modelBy">
          <j-search-select-tag
            v-model="model.modelBy"
            :trigger-change="true"
            dict="iot_device_model,name,id"
          />
        </a-form-model-item>
        <a-form-model-item ref="parentBy" :rules="rules.parentBy" label="上级实例" prop="parentBy">
          <a-tree-select
            v-model="model.parentBy"
            :allow-clear="true"
            :tree-data="parentInsSource"
            placeholder="请选择上级实例"
          />
        </a-form-model-item>
        <a-form-model-item ref="sysOrgCode" :rules="rules.sysOrgCode" label="所属机构" prop="sysOrgCode">
          <j-tree-select
            v-model="model.sysOrgCode"
            :trigger-change="true"
            dict="sys_depart,depart_name,org_code"
            pidField="parent_id"
            placeholder="请选择组织机构"
          >
          </j-tree-select>
        </a-form-model-item>
        <a-form-model-item ref="sceneBy" :rules="rules.sceneBy" label="所属场景" prop="sceneBy">
          <a-select
            v-model="model.sceneBy"
            :disabled="model.parentBy !== undefined && model.parentBy !== ''"
          >
            <a-select-option v-for="scene in sceneSource" :key="scene.value">
              {{ scene.text }}
            </a-select-option>
          </a-select>
        </a-form-model-item>
        <a-form-model-item ref="sceneSchemeBy" :rules="rules.sceneSchemeBy" label="场景方案" prop="sceneSchemeBy">
          <a-select
            v-model="model.sceneSchemeBy"
            :disabled="model.parentBy !== undefined && model.parentBy !== ''"
          >
            <a-select-option v-for="sceneScheme in sceneSchemeSource" :key="sceneScheme.value">
              {{ sceneScheme.text }}
            </a-select-option>
          </a-select>
        </a-form-model-item>
        <a-form-model-item ref="description" label="说明" prop="description">
          <a-textarea v-model="model.description" placeholder="请输入说明" rows="4" />
        </a-form-model-item>
        <template v-if="model.extendParams">
          <template v-for="(extendParam, extendParamIndex) in model.extendParams">
            <a-card :key="extendParamIndex" :hoverable="true" :title="'功能定义：' + extendParam.name" style="margin-bottom: 10px">
              <a-form-model-item
                v-for="(inputParam, inputParamIndex) in extendParam.inputParams"
                :key="inputParam.id"
                :ref="inputParam.code"
                :label="inputParam.name"
                :prop="'extendParams.'+extendParamIndex+'.inputParams.'+inputParamIndex+'.formatValue'"
                :rules="inputParam.rules"
              >
                <template v-if="'string,ip,ipPort,address'.indexOf(inputParam.type) !== -1">
                  <a-input
                    v-model="inputParam.formatValue"
                    :placeholder="'请输入' + inputParam.name"
                  />
                </template>
                <template v-if="'int,float,double'.indexOf(inputParam.type) !== -1">
                  <a-input-number
                    v-model="inputParam.formatValue"
                    :max="inputParam.metadata.max"
                    :min="inputParam.metadata.min"
                    :placeholder="'请输入' + inputParam.name"
                    :precision="inputParam.metadata.accuracy"
                  />
                  &nbsp;<a-tag color="blue">{{ inputParam.metadata.unit }}</a-tag>
                </template>
                <template v-if="'bool'.indexOf(inputParam.type) !== -1">
                  <a-switch
                    v-model="inputParam.formatValue"
                    :checked="model.extendParams[extendParam.code][inputParam.code]"
                    :checkedChildren="inputParam.metadata.trueText"
                    :unCheckedChildren="inputParam.metadata.falseText"
                  />
                </template>
                <template v-if="'array,vector3'.indexOf(inputParam.type) !== -1">
                  <a-textarea
                    v-model="inputParam.formatValue"
                    :placeholder="'请输入' + inputParam.name"
                    :rows="3"
                    allowClear
                  ></a-textarea>
                </template>
              </a-form-model-item>
            </a-card>
          </template>
        </template>
      </a-form-model>
    </a-spin>
    <div
      :style="{
        position: 'absolute',
        right: 0,
        bottom: 0,
        width: '100%',
        borderTop: '1px solid #e9e9e9',
        padding: '10px 16px',
        background: '#fff',
        textAlign: 'right',
        zIndex: 1
      }"
    >
      <a-button :style="{ marginRight: '10px' }" type="primary" @click="handleOk">确定</a-button>
      <a-button type="" @click="close">取消</a-button>
    </div>
  </a-drawer>
</template>

<script>
import pick from 'lodash.pick'
import {validateDuplicateValue} from '@/utils/util'
import JSearchSelectTag from '@/components/dict/JSearchSelectTag'
import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
import {getAction, httpAction} from '@api/manage'
import JTreeSelect from '../../../../../components/jeecg/JTreeSelect'

export default {
  name: 'DeviceInstanceModal',
  components: {
    JTreeSelect,
    JSearchSelectTag,
    JSelectDepart
  },
  data() {
    return {
      form: this.$form.createForm(this),
      title: '操作',
      width: 500,
      visible: false,
      showParentBy: false,
      extendParams: {},
      functions: [],
      model: {
        extendParams:[]
      },
      parentInsSource: [],
      orgSource: [],
      sceneSchemeSource: [],
      sceneSource: [],

      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      },
      confirmLoading: false,
      rules: {
        parentBy: [],
        code: [
          { required: true, message: '请输入实例标识!', trigger: 'change' },
          { min: 3, max: 30, message: '实例标识长度为3-30个字符', trigger: 'change' },
          {
            validator: (rule, value, callback) =>
              validateDuplicateValue('iot_device_instance', 'code', value, this.model.id, callback),
            trigger: 'change'
          }
        ],
        name: [
          { required: true, message: '请输入实例名称!' },
          { min: 3, max: 30, message: '实例名称长度为3-30个字符' }
        ],
        modelBy: [{ required: true, message: '请选择设备模型!' }],
        sysOrgCode: [{ required: true, message: '请输入所属机构!' }],
        sceneBy: [{ required: true, message: '请选择所属场景!' }],
        sceneSchemeBy: [{ required: true, message: '请选择场景方案!' }]
      },
      url: {
        add: '/device/instance/add',
        edit: '/device/instance/edit',
        getFunctionParams: '/device/instance/getFunctionParams',
        get: '/device/instance/queryById',
        listParent: '/device/instance/listParentInstanceByCurrentOrg',
        listScene: '/scene/manage/listSceneByCurrentOrg',
        listSchemeByScene: '/scene/sceneScheme/listBySceneId'
      }
    }
  },
  computed: {
    deviceModelBy() {
      return this.model.modelBy
    },
    parentBy() {
      return this.model.parentBy
    },
    sceneBy() {
      return this.model.sceneBy
    }
  },
  watch: {
    deviceModelBy(val, oval) {
      console.log('watch-deviceModelBy', oval, '=>', val)
      this.getFunctionParams(val)
    },
    parentBy(val, oval) {
      console.log('1、上级设备变动===>>', oval, '=>', val)
      if (val !== '') this.resetScene()
      this.getScene()
      this.getInstanceByParentId(val)
    },
    sceneBy(val, oval) {
      console.log('watch-sceneBy', oval, '=>', val)
      if (oval !== undefined) this.resetSceneScheme()

      this.getSchemeByScene(val)
    }
  },
  methods: {
    validatorPattern(type, metadata) {
      let validatorPattern = { pattern: '', message: '' }
      if (type === 'array') {
        switch (metadata.arrayType) {
          case 'byte':
            validatorPattern.pattern = `^([0-9a-fA-F]{2}${metadata.arraySplit}){${metadata.arraySize - 1}}[0-9a-fA-F]{2}$`
            validatorPattern.message = `请输入${metadata.arraySize}位byte类型以${metadata.arraySplit === ' ' ? '空格' : metadata.arraySplit}为分隔符的数组`
            break
          case 'int':
            validatorPattern.pattern = `^([0-9]${metadata.arraySplit}){${metadata.arraySize - 1}}[0-9]$`
            break
          default:
            validatorPattern.pattern = `^(.${metadata.arraySplit}){${metadata.arraySize - 1}}.$`
        }
        return validatorPattern
      } else if (type === 'ipPort') {
        return {
          pattern:
            '^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\:\\d{2,6}$',
          message: '请正确输入TCP地址[IP:PORT]',
          trigger: 'change'
        }
      } else if(type === "vector3") {
        return  {
          pattern: '^(\\-|\\+)?\\d+(\\.\\d+)?,(\\-|\\+)?\\d+(\\.\\d+)?,(\\-|\\+)?\\d+(\\.\\d+)?$',
          message: '请按正确格式输入三维向量数据',
          trigger: 'change'
        }
      }

      return null
    },
    getFunctionParams(modelId) {
      const scope = this
      if (modelId) {
        console.log('>>> 获取扩展参数 <<<')
        getAction(this.url.getFunctionParams, { instanceId: this.model.id || '', modelId: modelId }).then(res => {
          if (res.success) {
            scope.model.extendParams = res.result
            scope.model.extendParams.map(func =>{
              // 追加校验规则
              func.inputParams = func.inputParams
                // 过滤实例注入
                // .filter(filter => filter.inputMode === 'ins_input')
                .map(inputParam => {
                  inputParam['rules'] = []
                  inputParam.rules.push({ required: inputParam.inputMode === 'ins_input', message: '请填写' + inputParam.name + '!' })
                  let valid = scope.validatorPattern(inputParam.type, inputParam.metadata)
                  if(valid) {
                    inputParam.rules.push(valid)
                  }
                  // 删除metadata
                  // delete inputParam.metadata
                  return inputParam;
                })
                console.log(func)
            })
            console.log(scope.model.extendParams)
            scope.$forceUpdate()
          }
        })
      }
    },
    getInstanceByParentId(parentId) {
      if (parentId === undefined) return
      const scope = this
      getAction(this.url.get, { id: parentId }).then(res => {
        if (res.success) {
          scope.model.sysOrgCode = res.result.sysOrgCode
          scope.model.sceneBy = res.result.sceneBy
          scope.model.sceneSchemeBy = res.result.sceneSchemeBy
          scope.$nextTick(() => {
            console.log('4、根据上级设备，设置sysOrgCode、sceneBy、sceneSchemeBy', scope.model.sysOrgCode, scope.model.sceneBy, scope.model.sceneSchemeBy)
            this.form.setFieldsValue(pick(this.model, 'sysOrgCode', 'sceneBy', 'sceneSchemeBy'))
          })
        }
      })
    },
    /* 权限控制 */
    getParentInstance() {
      const scope = this
      getAction(this.url.listParent, {}).then(res => {
        if (res.success) {
          console.log('上级设备: ', res.result)
          scope.parentInsSource = res.result
        }
      })
    },
    getScene() {
      const scope = this
      this.sceneSource = []
      getAction(this.url.listScene, {}).then(res => {
        if (res.success) {
          console.log('2、获取所属场景===>> ', res.result)
          res.result.filter(scene => {
            scope.sceneSource.push({
              value: scene.id,
              text: scene.name
            })
          })
        }
      })
    },
    getSchemeByScene(sceneId) {
      const scope = this
      this.sceneSchemeSource = []
      if (sceneId === undefined || sceneId === '') {
        return
      }
      getAction(this.url.listSchemeByScene, { sceneId: sceneId }).then(res => {
        if (res.success) {
          console.log('3、获取场景方案===>> ', res.result)
          res.result.filter(scheme => {
            scope.sceneSchemeSource.push({
              value: scheme.id,
              text: scheme.name
            })
          })
        }
      })
    },
    resetParentInstance() {
      console.log('重置上级实例。。。')
      this.model.sceneBy = undefined
    },
    resetScene() {
      console.log('重置场景。。。')
      this.model.sceneBy = undefined
    },
    resetSceneScheme() {
      console.log('重置场景方案。。。')
      this.model.sceneSchemeBy = undefined
    },
    add() {
      let record = {
        sysOrgCode: '',
        modelBy: '',
        parentBy: '',
        sceneBy: '',
        sceneSchemeBy: '',
        isFirstLoad: true,
        extendParams:[]
      }
      this.edit(record)
    },
    edit(record) {
      const scope = this
      this.getParentInstance()
      this.model = Object.assign({}, { ...record })
      this.visible = true
      console.log(this.model)
    },
    close() {
      this.model = {}
      this.extendParams = []
      this.sceneSource = []
      this.$refs.instanceForm.resetFields()
      this.visible = false
    },
    handleOk() {
      const scope = this
      // 触发表单验证
      this.$refs.instanceForm.validate(valid => {
        if (valid) {
          scope.confirmLoading = true
          let httpurl = ''
          let method = ''
          if (!this.model.id) {
            httpurl += this.url.add
            method = 'post'
          } else {
            httpurl += this.url.edit
            method = 'put'
          }
          let formModel = JSON.parse(JSON.stringify(this.model))
          formModel.extendParams.map(extendParam => {
            // 注入instanceId
            extendParam['instanceId'] = formModel.id
            extendParam.inputParams.map(param => {
              delete param.metadata
              delete param.rules
              delete param.value
            })
          })
          console.log('提交表单', formModel)
          httpAction(httpurl, formModel, method)
            .then(res => {
              if (res.success) {
                scope.$message.success(res.message)
                scope.$emit('ok')
              } else {
                scope.$message.warning(res.message)
              }
            })
            .finally(() => {
              scope.confirmLoading = false
              scope.$refs.instanceForm.resetFields()
              scope.close()
            })
        } else {
          return false
        }
      })
    }
  }
}
</script>
